/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 *
 * $Id: TextData.hpp,v 1.5 2009-12-08 10:48:28 morsko Exp $
 *
 * \file
 * \brief MaCI - Text Data parser header
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 */
#ifndef _MACI_INTERFACE_TEXT_DATA_HPP_
#define _MACI_INTERFACE_TEXT_DATA_HPP_

#include "TextTypes.hpp"
#include "timestamp.hpp"
#include "MaCIData.hpp"
#include <stdio.h>
#include <vector>

namespace gim {
  namespace binbag{class CBinBag;}
}

namespace MaCI {
  namespace Text {

    /** Text Data Decoder/Encoder.
     * This class implements 
     *
     */
    class CTextData : public CMaCIData
    {
    public:
      /** Constructor.
       *
       */
      CTextData(void);


      /** Destructor.
       *
       */
      ~CTextData(void);
      
      /** Copy constructor for TextData. 
       *
       * The copy constructor duplicates the input object to maximum
       * depth (All containers are duplicated too). After a copy is
       * constructed, no dependencies to original Data element exist.
       *
       * @param[in] aTextData Reference to CTextData 
       *            container to copy.
       */
      CTextData(const CTextData &aTextData);

      

      /** Assignment operator for TextData.
       *
       * The assignment operator duplicates the input object to
       * maximum depth (All containers are duplicated too). After a
       * copy is constructed, no dependencies to original Data element
       * exist.
       *
       * @param[in] aTextData Reference to CTextData 
       *            container to copy.
       */
      CTextData &operator=(const CTextData &aTextData);

      ///////////////////////////////////////////////////
      // Derived from 'CMaCIData', see description there.
      bool DecodeFrom(gim::binbag::CBinBag *aBinBag = NULL);
      void Reset();
      void Print(const int level) const;
      ///////////////////////////////////////////////////


      /** Set Command element.
       *
       * Command elements must be accompanied by related dataelement
       * when required by commandtype. See the command enumerations
       * for a note about required datatype. (For example, 'SetText'
       * command required a 'TText' datatype after the command.
       * 
       * \see TCommand
       *
       * @param[in] aCmd        Command element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetCommand(const TCommand &aCmd);

      /**
       * Set TText-Structure. 
       * NOTE: You must set Text header before using this
       * NOTE: For easier use, use SetText(std::string)-function
       * instead. By using it you don't have to add TextHeader.
       * 
       * @param[in] aText       TText-structure to add
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetText(const TText &aText);

      /**
       * Sets a std::string to TextData-container. This function adds 
       * a TTextHeader- and n amount of TText- structures. 
       *
       * @param aText           std::string to add
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetText(const std::string &aText);

      /**
       * Set TTextHeader-structrure
       * Set this before setting any text to define how many TText-structure 
       * will be after this header
       *
       * @param aHeader         Header structure to add
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetTextHeader(const TTextHeader &aHeader);




      /** Get constant pointer to TCommand element (if such exists).
       *
       * \see TCommand
       * 
       * @return                Constant pointer to command
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TCommand *GetCommand(void) const
      {
        return iCommandPtr;

      }

      /** 
       * Tells if the currrent TextData is valid. It's not valid if it's empty,
       * or there are less text-structure than said in the header
       *
       * @return        Boolean value if the data is valid
       */
      bool IsValid(void);

      /**
       * Returns the TText structure pointer with wanted index
       * set to TextData. TTextHeader tells how many Text elements
       * can be found at TextData. If yo uwant the whole text inside
       * CTextData, use GetWholeText-function.
       *
       * @return               TText-structure pointer
       */
      const TText *GetText(unsigned int aIndex) const
      {
	const TText *elem = NULL;
	

	if (aIndex >= 0 && 
	    aIndex < iTextElementCount && 
	    iTextPtr != NULL) {
	  
	  const char *cptr = (const char *)iTextPtr;
	  cptr += aIndex * (sizeof(TText) + sizeof(gim::binbag::TBinBlob));
	  
	  // Now, typecast the address to Element.
	  elem = (const TText *)cptr;
	}
		
	return elem;
       
      }

      const TTextHeader *GetTextHeader(void) const
      {

        return iTextHeaderPtr;

      }


      /**
       * Returns the whole text in std::string
       * 
       * @param aText         Reference to std::string where to whole text
       *                      is saved.
       * @return              True if succeded, false if failed to decode.
       */ 
      bool GetWholeText(std::string &aText);
     
    private:
      bool iValid;
      
      const TCommand *iCommandPtr; ///< Pointer to command if any.
      const TText *iTextPtr; ///< Pointer to text
      const TTextHeader *iTextHeaderPtr; ///< Pointer to text header
      unsigned int iTextElementCount; ///< For analysing packet correctness
      unsigned int iHeaderTextElementCount; ///< Number of elements set in header.
    };
  }

}



#endif ///< _MACI_INTERFACE_TEXT_DATA_HPP_
